home *** CD-ROM | disk | FTP | other *** search
- property pMyContainer : "" --path to the folder that contains your experiment script
- property pResourcesFolderName : "Resources" -- name of the folder in which you store images etc.
- property pPathtoResultsFolder : "" --Full path to the folder in which results will be stored.
- --e.g., "MacHD:PsyScriptΔí:scripts:Experiments:Eyemovement:SPEMΔí:Results:"
- property pResultsFolderName : "Results"
- property pResultsFileRef : "" -- a place to store results before you write them to disk
- property psubjectID : "" --the name of the data file
- property pSubjectDataFile : "" --path to the data file (including the name)
- property pResponses : {}
- property pKeyState : "" --contents of every key for restoring to a previous state
-
- property qlist : {} -- used to link the qsort helper to the sort handler
- -- >> PsyScript Management Functions ***************
-
- (* to killTheControlStrip()
- tell application "Control Strip"
- quit
- end tell
- end killTheControlStrip
- *)
-
-
- on quitAllExcept(appstokeepalive) --{list of app names}
- try
- my kill_the_control_strip()
- end try
- try
- get the path to frontmost application --me
- tell application "Finder"
- set myName to the name of the result
- set processesToKill to (the name of every process whose file type is "APPL" and name is not myName and creator type is not "PsyS") as list
- repeat with thisApp in processesToKill
- tell application thisName to quit
- end repeat
- if "Finder" is not in appstokeepalive then
- quit
- set end of processesToKill to "Finder"
- end if
- return processesToKill
- end tell
- end try
- end quitAllExcept
-
- to initialize()
- --sets the filepaths to the script, resources and results folders
- set pResponses to {} --initialize the response list to empty, just to be safe.
- --set default picture folder
- tell application "PsyScript"
- set AppleScript's text item delimiters to ""
- activate
- --set my container
- set the_filepath to (path to me) as text
- set lastColon to the offset of ":" in (the reverse of every character of the_filepath) as string
- set pMyContainer to (text 1 thru -(lastColon) of the_filepath)
-
- --try and initialise path to resources
- try
- set pathToTry to pMyContainer & pResourcesFolderName & ":"
- get info for file pathToTry
- set default picture folder to pathToTry
- on error tmsg number tnum
- if tnum = -35 then
- error "could not find folder \"" & pResourcesFolderName & "\" beside this script
- I was looking here:
- " & pathToTry
- else
- error tmsg & return & "source: initializeFilePaths" number tnum
- end if
- end try
- --also try and initialise path to results
- try
- set pPathtoResultsFolder to pMyContainer & pResultsFolderName & ":"
- list folder pPathtoResultsFolder --fails the try if folder does not exist
- on error tmsg number tnum
- try
- tell application "Finder"
- make new folder in folder pMyContainer with properties {name:pResultsFolderName}
- end tell
- on error
- error "Could not find or create folder \"" & pPathtoResultsFolder & "\" beside this script.
- Create a folder called \"results\" along side the script
- (source = initialize())"
- end try
- end try
- return default picture folder
- end tell
- end initialize
-
- to setPathToResources() --sets default picture folder
- tell application "PsyScript"
- set AppleScript's text item delimiters to ""
- activate
- --set my container
- set the_filepath to (path to me) as text
- set lastColon to the offset of ":" in (the reverse of every character of the_filepath) as string
- set pMyContainer to (text 1 thru -(lastColon) of the_filepath)
- --try and initialise path to resources
- try
- set pathToTry to pMyContainer & pResourcesFolderName & ":"
- get info for file pathToTry
- set default picture folder to pathToTry
- on error tmsg number tnum
- if tnum = -35 then
- error "could not find folder \"" & pResourcesFolderName & "\" beside this script
- I was looking here:
- " & pathToTry
- else
- error tmsg & return & "source: setPathToResources" number tnum
- end if
- end try
- end tell
- end setPathToResources
-
- to createNewSubjectID()
- --locates or creates the results folder
- --gets a subject ID via dialog, checks that no corresponding file exists
- --returns a subjectID
- tell application "PsyScript"
- activate
- try
- list folder pPathtoResultsFolder --fails the try if folder does not exist
- on error errormessage number errorNumber
- if errorNumber = -35 then
- try
- tell application "Finder"
- make new folder in folder pMyContainer with properties {name:pResultsFolderName}
- end tell
- on error
- error "Create a folder called \"results\" along side the script
- (source = createNewSubjectID)"
- end try
- else
- error errormessage & return & "(source = createNewSubjectID)" number errorNumber
- end if
- end try
- set thePrompt to "Enter your Subject ID"
- set notUnique to true
- repeat while notUnique
- try
- display dialog thePrompt default answer ""
- set psubjectID to the text returned of the result
- if psubjectID = "" then
- set thePrompt to "Must enter at least 1 character"
- else
- set pSubjectDataFile to pPathtoResultsFolder & psubjectID as string
- tell application "Finder"
- if exists file pSubjectDataFile then --hopefully this fails (and the id is not taken)
- --was able to read that file:ask if the user want to reuse it
- display dialog "The Identifier " & psubjectID & "already exists
- Would you like to overwrite this, append new data, or choose a new ID?" buttons {"overwrite", "append", "choose new"} default button "choose new"
- set userChoice to the button returned of the result
- if userChoice is "append" then
- exit repeat
- else if userChoice is "overwrite" then
- set eof of file pSubjectDataFile to 0
- exit repeat
- else
- set thePrompt to "That Subject ID is already taken: try another"
- end if
- else
- set notUnique to false
- end if
- end tell
- end if
- on error
- error "problem creating new subject ID."
- end try
- end repeat
- return psubjectID
- end tell
- end createNewSubjectID
-
- to setResultsFile(pathToResultsFile)
- --use this only if you do not use getvalidsubjectID
- set pSubjectDataFile to pathToResultsFile
- end setResultsFile
-
- to writespreadsheet(theData) --you can pass this a string, a list of strings, a record, or a list of lists! all of them work.
- if class of theData is record then set theData to theData as list
- if (class of theData is list) then
- set oldDelims to AppleScript's text item delimiters
- set AppleScript's text item delimiters to {tab}
- if (class of item 1 of theData is not list) then set theData to {theData}
- try
- set f to open for access pSubjectDataFile with write permission
- write "" to f starting at eof
- on error theMessage number thenumber
- if thenumber = -1409 then
- error "Probably you did not define a subject file, do this with createNewSubjectID" & ¬
- return & theMessage & return & "(source = writeSpreadsheet(theData))"
- else
- error theMessage & return & "(source = writeSpreadsheet(theData))"
- end if
- end try
- try
- repeat with aline in theData
- try
- write "" & aline & return to f
- on error theMessage number errNumber
- set AppleScript's text item delimiters to oldDelims
- close access pSubjectDataFile
- error theMessage & return & "(source = writeSpreadsheet(theData))"
- end try
- end repeat
- close access pSubjectDataFile
- on error theMessage number errNumber
- set AppleScript's text item delimiters to oldDelims
- close access pSubjectDataFile
- error theMessage & return & "(source = writeSpreadsheet(theData))"
- end try
- else --is not a list or a record. Either already text or else a number
- try --could use tanaka
- set f to open for access pSubjectDataFile with write permission
- write ("" & theData & return) to f starting at eof
- close access f
- on error
- close access pSubjectDataFile
- error "Failed to open, or write to " & pSubjectDataFile & return & "(source = writeSpreadsheet(theData))"
- end try
- end if
- end writespreadsheet
-
- --use this to write companion files, files which record data to standalone files with the same base name as pSubjectDataFile
- to writeToCompanionFile(theData, fileSuffix) --you can pass this a string, a list of strings, a record, or a list of lists! all of them work.
- set fileName to (pSubjectDataFile & fileSuffix)
- if class of theData is record then set theData to theData as list
- if (class of theData is list) then
- set oldDelims to AppleScript's text item delimiters
- set AppleScript's text item delimiters to {tab}
- if (class of item 1 of theData is not list) then set theData to {theData}
- try
- set f to open for access fileName with write permission
- write "" to f starting at eof
- on error theMessage number thenumber
- if thenumber = -1409 then
- error "Probably you did not define a subject file, do this with createNewSubjectID" & ¬
- return & theMessage & return & "(source = writeToCompanionFile(theData,fileSuffix))"
- else
- error theMessage & return & "(source = writeToCompanionFile(theData,fileSuffix))"
- end if
- end try
- try
- repeat with aline in theData
- try
- write (aline as string) & return to f
- on error theMessage number errNumber
- set AppleScript's text item delimiters to oldDelims
- close access fileName
- error theMessage & return & "(source = writeToCompanionFile(theData,fileSuffix))"
- end try
- end repeat
- close access fileName
- on error theMessage number errNumber
- set AppleScript's text item delimiters to oldDelims
- close access fileName
- error theMessage & return & "(source = writeToCompanionFile(theData,fileSuffix))"
- end try
- else --is not a list or a record. Either already text or else a number
- try --could use tanaka
- set f to open for access fileName with write permission
- write ("" & theData & return) to f starting at eof
- close access f
- on error
- close access fileName
- error "Failed to open, or write to " & fileName & return & "(source = writeToCompanionFile(theData,fileSuffix))"
- end try
- end if
- end writeToCompanionFile
-
- --probably won't use this much - you can just call writespreadsheet() directly
- --it is useful if you need speed and therefore cannot afford to write the results to disk each trial.
-
- on storeResults(newResponses, flushtoDisk)
- set end of pResponses to newResponses
- if flushtoDisk then
- writespreadsheet(pResponses)
- set pResponses to {}
- end if
- end storeResults
-
-
- (* to cleanup()
- tell application "PsyScript"
- end experiment
- try
- close access my pSubjectDataFile
- end try
- end tell
- tell application "Finder" to launch
- tell application "Control Strip" to launch
- end cleanup
- *)
-
-
- -- >> LIST HANDLERS
- --use these to read in lists from files
- --modified 2001/04/23
- --fixed up file closing
- on readSpreadsheet(thefile) --takes a file path, returns a 2D array.
- set outArray to {}
- set oldDelims to AppleScript's text item delimiters
- set AppleScript's text item delimiters to {tab}
- if ":" is not in thefile then set thefile to (pMyContainer & pResourcesFolderName & ":" & thefile)
- try
- set f to open for access thefile
- on error m number N
- error "could not open the file :" & thefile & return & "Source:readspreadsheet()" & return & m number N
- end try
-
- repeat
- try
- set end of outArray to (every text item of (read f before return))
- on error theMessage number errNumber
- try
- close access f
- end try
- set AppleScript's text item delimiters to oldDelims
- if errNumber = -39 then -- end of file, clean up & get out
- return outArray
- else -- different type of error. Clean up & resignal user
- error theMessage & return & "readspreadsheet" number N
- end if
- end try
- end repeat
- try
- close access f
- end try
- return outArray
- end readSpreadsheet
-
- on readSpreadsheet1D(thefile) --takes a file path, returns a 1D array.
- set outArray to {}
- if ":" is not in thefile as string then set thefile to (pMyContainer & pResourcesFolderName & ":" & thefile)
- try
- set f to open for access thefile
- on error m number N
- error "could not open the file :" & thefile & return & "Source:readspreadsheet()" & return & m number N
- end try
-
- repeat
- try
- set end of outArray to (read f before return)
- on error theMessage number errNumber
- try
- close access f
- end try
- if errNumber = -39 then -- end of file, clean up & get out
- return outArray
- else -- different type of error. Clean up & resignal user
- error theMessage & return & "readspreadsheet" number errNumber
- end if
- end try
- end repeat
- try
- close access f
- end try
- return outArray
- end readSpreadsheet1D
-
-
- --initializeList(5, "0")
- -->{"0", "0", "0", "0", "0"}
- to initializeList(theCount, theContents)
- set TheList to {}
- repeat with N from 1 to theCount
- set the end of TheList to theContents
- end repeat
- return TheList
- end initializeList
-
- --getOffset(6, {1, 2, 3})
- -->-1
- on getOffset(what, TheList) -- return -1 if not found
- repeat with i from 1 to (count of TheList)
- if item i of TheList is what then return i
- end repeat
- return -1 --
- end getOffset
-
- on sort(TheList)
- set qlist to TheList
- my qsort(a reference to qlist, 1, count of qlist)
- return qlist
- end sort
-
- --qsort is used by sort
- on qsort(the_list, startIndex, finishIndex)
- set i to startIndex
- set j to finishIndex
- set mid to item ((i + j) div 2) of the_list
- repeat
- repeat while ((item i of the_list) < mid)
- set i to i + 1
- end repeat
- repeat while ((item j of the_list) > mid)
- set j to j - 1
- end repeat
- if i ‚â§ j then
- set {item i of the_list, item j of the_list} to {item j of the_list, item i of the_list}
- set {i, j} to {i + 1, j - 1}
- end if
- if i > j then exit repeat
- end repeat
-
- if j > startIndex then qsort(the_list, startIndex, j)
- if i < finishIndex then qsort(the_list, i, finishIndex)
- end qsort
-
- to randomize(TheList)
- repeat with i from length of TheList to 1 by -1
- set current_item to (random number from 1 to i)
- tell TheList -- exchange item current_item with item i
- set temp to item i
- set item i to item current_item
- set item current_item to temp
- end tell
- end repeat
- return TheList
- end randomize
-
-
- --returns the distinct elements of a list
- to distinct(TheList)
- set outList to {}
- repeat with anItem in TheList
- if anItem is not in outList then
- set end of outList to contents of anItem
- end if
- end repeat
- return anItem
- end distinct
-
- to union(listA, listB)
- set c to listA & listB
- return my distinct(c)
- end union
-
- to intersection(listA, listB)
- set outList to {}
- repeat with anItem in listA
- if (anItem is in listB) then set end of outList to contents of anItem
- end repeat
- return outList
- end intersection
-
- to difference(listA, listB)
- set outList to {}
- repeat with anItem in listA
- if (anItem is not in listB) then set end of outList to contents of anItem
- end repeat
- return outList
- end difference
-
- --return insert(3, "first after 3", {1, 2, 3, 4})
- --{1, 2, 3, "first after 3", 4}
- --return insert({3, 2}, {"first after 3", "second after 2"}, {1, 2, 3, 4})
- --{1, 2, "second after 2", 3, "first after 3", 4}
- to insert(insertionAt, addingTheseItems, toThisList) --insertion item must come in reverse order!!
- local N
- if class of insertionAt is list then
- if class of addingTheseItems is not list then
- error "NewItems parameter for insertItemsAfter must be list" number -1719
- else if class of toThisList is not list then
- error ("originalList parameter for insertItemsAfter must be list not " & (class of toThisList as string)) number -1719
- else if (count of insertionAt) ≠ (count of addingTheseItems) then
- error "insertItemsAfter says \"insertionCount & count of NewItems must be equal\"" number -1719
- else
- repeat with N from 1 to count of insertionAt
- set toThisList to insert(item N of insertionAt, item N of addingTheseItems, toThisList)
- end repeat
- return toThisList
- end if
- else --inserting 1 item
- copy (insertionAt as number) to x
- if x = 0 then
- return {} & addingTheseItems & toThisList --prepend if index is <1
- else if (x ‚â• (count toThisList)) then
- return (toThisList & addingTheseItems) --append if is large index
- else if x = 1 then
- return (item 1 of toThisList) & addingTheseItems & (items (x + 1) thru -1 of toThisList)
- else
- return (items 1 thru (x) of toThisList) & addingTheseItems & (items (x + 1) thru -1 of toThisList)
- end if
- end if
- end insert
-
- --replaceItems({1, -1}, {"a", "b"}, {1, 2, 3, 4})
- -->{"a", 2, 3, "b"}
- to replaceItems(itemIndices, NewItems, originalList)
- copy originalList to scratchList
- if class of itemIndices is not list then
- error "insertionIndices parameter for replaceItemsAt must be list" number -1719
- else if class of NewItems is not list then
- error "NewItems parameter for replaceItemsAt must be list" number -1719
- else if class of originalList is not list then
- error "originalList parameter for replaceItemsAt must be list not " & (class of originalList) number -1719
- else
- set N to count of itemIndices
- repeat with x from 1 to N
- set item (item x of itemIndices) of scratchList to (contents of item x of NewItems)
- end repeat
- return scratchList
- end if
- end replaceItems
-
-
- --parsetostring({{1, 2, 3, 4}, {"a", "b", "c", "d"}}, {"•", return})
- -->1•2•3•4
- -->a•b•c•d
- on parsetostring(TheList, theDelimiters)
- if (count of theDelimiters) > 1 then
- (* if class of item 1 of TheList is not list then
- error "you gave delimiters suggesting a 2D array but I only see 1D"
- else *)
- if ((count of theDelimiters) > 2) then
- error "I can only do a 2D string so far"
- else
- set outstring to ""
- repeat with aline in TheList
- set outstring to outstring & my parsetostring(aline, item 1 of theDelimiters) & item 2 of theDelimiters
- end repeat
- end if
- else --1D
- set savedTextItemDelimiters to AppleScript's text item delimiters
- try
- set AppleScript's text item delimiters to {theDelimiters}
- set TheList to TheList as string
- set AppleScript's text item delimiters to savedTextItemDelimiters
- return TheList
- on error errMsg number errNum from f to t partial result p
- --also reset text item delimiters in case of an error:
- set AppleScript's text item delimiters to savedTextItemDelimiters
- --and resignal the error:
- return TheList --is this a bug?
- error errMsg number errNum from f to t partial result p
- end try
- end if
- end parsetostring
-
- on stringToList(theString, theDelimiters) --
- --note this will create lists for every delimiter even if the delimiter is not found
- --i.e., the list is packed to a square array
-
- set outList to {}
- set savedTextItemDelimiters to AppleScript's text item delimiters
- try
- set AppleScript's text item delimiters to {item 1 of theDelimiters}
- set theStringAsList to every text item of theString
- set AppleScript's text item delimiters to savedTextItemDelimiters
- on error errMsg number errNum from f to t partial result p
- --also reset text item delimiters in case of an error:
- set AppleScript's text item delimiters to savedTextItemDelimiters
- --and resignal the error:
- error errMsg number errNum from f to t partial result p
- end try
- --recurse over this result if we still have delimiters in our pocket
- if (count of theDelimiters) > 1 then --we are making a multidimensionalList
- set newDelimiterList to items 2 through -1 of theDelimiters
- repeat with aline in theStringAsList
- set end of outList to my stringToList(aline, newDelimiterList)
- end repeat
- else
- set outList to theStringAsList
- end if
- return outList as list
- end stringToList
-
-
- to subset(indices, TheList)
- set outList to {}
- if class of indices is not list then
- return {}
- else
- repeat with itemIndex in indices
- set end of outList to item (itemIndex as number) of TheList
- end repeat
- return outList
- end if
- end subset
-
- on removeItem(x, TheList) --at x --, theList)
- -- removes any item from a list
- set x to (x as number)
- if x < 1 then return TheList
- set numItems to count of items in TheList
- if numItems is 1 then return {}
- if x > numItems then return TheList
- if x = 1 then
- set newList to (items 2 thru -1 of TheList)
- else if x = numItems then
- set newList to (items 1 thru -2 of TheList)
- else
- set newList to (items 1 thru (x - 1) of TheList) & (items (x + 1) thru -1 of TheList)
- end if
- return newList
- end removeItem
-
- --sample with Replacement given take:3, outof:{1, 2, 3, 4, 5, 6, 7, 8, 9}
- -->{3, 9, 7}
- --sample without Replacement given take: 3 outof: {1, 2, 3, 4, 5, 6, 7, 8, 9}
- -->{3, 9, 7}
-
- to sample(itemCount, TheList, replacing)
- if itemCount > length of TheList then
- error "source:sample(itemcount, thelist, replacing):
- Asked for more items than exist"
- else
- set chosenItems to {}
- if replacing then
- repeat with N from 1 to itemCount
- set end of chosenItems to some item of TheList
- end repeat
- else
- set chosenItems to items 1 thru itemCount of (my randomize(TheList))
- end if
- return chosenItems
- end if
- end sample
-
-
- --makeASparseList given taking:10, outof:{}, separatedBy:4
- -->{5, 7, 3}
- on sparseRepeat given taking:numberWanted, outof:TheList, separatedBy:min
- set outList to {}
- set separationCheckList to {}
- repeat while (count of outList) < numberWanted
- set candidate to (some item of TheList)
- if candidate is not in separationCheckList then
- set outList to outList & candidate
- set separationCheckList to separationCheckList & candidate
- if (count of separationCheckList) > min then set separationCheckList to items -min thru -1 of separationCheckList
- end if
- end repeat
- return outList
- end sparseRepeat
-
- --Author = Chris Espinosa <cde@apple.com>
- to create_shuffled_list(listLength)
- set orderedList to {}
- repeat with N from 1 to listLength
- set end of orderedList to N
- end repeat
- set shuffledList to {}
- repeat listLength times
- set chosenItem to 0
- repeat until chosenItem is not 0
- set chosenItem to some item of orderedList
- end repeat
- set end of shuffledList to chosenItem
- set item chosenItem of orderedList to 0
- end repeat
- return shuffledList
- end create_shuffled_list
-
-
- -->create_shuffled_sublist(56, 6)
- -- {38, 13, 32, 52, 40, 8}
- to create_shuffled_sublist(totalNumberSet, listLength)
- set orderedList to {}
- repeat with N from 1 to totalNumberSet
- set end of orderedList to N
- end repeat
- set shuffledList to {}
- repeat listLength times
- set chosenItem to 0
- repeat until chosenItem is not 0
- set chosenItem to some item of orderedList
- end repeat
- set end of shuffledList to chosenItem
- set item chosenItem of orderedList to 0
- end repeat
- return shuffledList
- end create_shuffled_sublist
-
-
-
- -->>KEY FUNCTIONS
- on saveKeyStates()
- tell application "PsyScript"
- set pKeyState to contents of every key
- end tell
- end saveKeyStates
-
- on restoreKeyStates()
- tell application "PsyScript"
- repeat with aKey in pKeyState
- set zz to name of aKey
- set noticed of key zz to noticed of aKey
- set mapping of key zz to mapping of aKey
- end repeat
- end tell
- end restoreKeyStates
-
- on setNoticed of keyName given mapping:theMapping --setNoticed of "K" given mapping:"name you want"
- tell application "PsyScript"
- tell key keyName
- set noticed to true
- set mapping to theMapping
- end tell
- end tell
- end setNoticed
-
- to noticeKeyboard(keyList) --keyList of form {{"name","mapping"},{"name","mapping"}}
- tell application "PsyScript"
- set response type to keyboard response
- if keyList is {} then
- set noticed of every key to true
- else
- set noticed of every key to false
- repeat with theKey in keyList
- tell key (item 1 of theKey)
- set mapping to item 2 of theKey
- set noticed to true
- end tell
- end repeat
- end if
- end tell
- end noticeKeyboard
-